home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1999 March
/
EnigmA AMIGA RUN 35 (1999)(G.R. Edizioni)(IT)[!][issue 1999-03].iso
/
earcd
/
utils
/
xad
/
developer
/
sources
/
tools
/
xadunfile.c
< prev
Wrap
C/C++ Source or Header
|
1999-01-01
|
13KB
|
432 lines
#define NAME "xadUnFile"
#define DISTRIBUTION "(Freeware) "
#define REVISION "4"
/* Programmheader
Name: xadUnFile
Author: SDI
Distribution: Freeware
Description: dearchives file archives
Compileropts: -
Linkeropts: -gsi -l amiga
1.0 13.09.98 : first version
1.1 18.11.98 : added FILE parameter and directory creation
1.2 03.02.99 : added corrupt message
1.3 07.02.99 : added missing "group crunched" handling
1.4 16.03.99 : errors no longer abort decrunching
*/
#include <proto/xadmaster.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <exec/memory.h>
#include <dos/dosasl.h>
#include <utility/hooks.h>
#include "SDI_defines.h"
#include "SDI_compiler.h"
#define SDI_TO_ANSI
#include "SDI_ASM_STD_protos.h"
struct xadMasterBase * xadMasterBase = 0;
struct DosLibrary * DOSBase = 0;
struct ExecBase * SysBase = 0;
#define PARAM "FROM/A,DESTDIR,PASSWORD/K,FILE/M,NE=NOEXTERN/S," \
"INFO=LIST/S,OW=OVERWRITE/S,NOTREE/S,ASKMAKEDIR/S," \
"NOCOMMENT/S,NOPROT/S,NODATE/S,NOABS/S"
#define OPTIONS \
"FROM The input archive file (no patterns allowed)\n" \
"DESTDIR The destination directory, not needed with INFO\n" \
"PASSWORD A password for encrypted archives\n" \
"FILE Multiple filenames (with patterns) to be extracted\n" \
"NOEXTERN Turns off usage of external clients\n" \
"INFO Shows archive information without extracting\n" \
"OVERWRITE Files are overwritten without asking\n" \
"NOTREE Files are extracted without subdirectories\n" \
"ASKMAKEDIR You get asked before a directory is created\n" \
"NOCOMMENT No filenote comments are extracted or displayed\n" \
"NOPROT Protection information gets not extracted\n" \
"NODATE Creation date information gets not extracted\n" \
"NOABS Do not extract absolute path name parts\n"
struct xHookArgs {
STRPTR name;
ULONG flags;
ULONG finish;
};
struct Args {
STRPTR from;
STRPTR destdir;
STRPTR password;
STRPTR * file;
ULONG noextern;
ULONG info;
ULONG overwrite;
ULONG notree;
ULONG askmakedir;
ULONG nocomment;
ULONG noprot;
ULONG nodate;
ULONG noabs;
};
ASM(ULONG) progrhook(REG(a0, struct Hook *),
REG(a1, struct xadProgressInfo *));
LONG CheckName(STRPTR *pat, STRPTR name);
ULONG start(void)
{
ULONG ret = RETURN_FAIL;
struct DosLibrary *dosbase;
SysBase = (*((struct ExecBase **) 4));
{ /* test for WB and reply startup-message */
struct Process *task;
if(!(task = (struct Process *) FindTask(0))->pr_CLI)
{
WaitPort(&task->pr_MsgPort);
Forbid();
ReplyMsg(GetMsg(&task->pr_MsgPort));
return RETURN_FAIL;
}
}
if((dosbase = (struct DosLibrary *) OpenLibrary("dos.library", 37)))
{
LONG err = 0;
struct xadMasterBase *xadmasterbase;
DOSBase = dosbase;
if((xadmasterbase = (struct xadMasterBase *)
OpenLibrary("xadmaster.library", 1)))
{
struct Args args;
struct RDArgs *rda;
memset(&args, 0, sizeof(struct Args));
xadMasterBase = xadmasterbase;
if((rda = (struct RDArgs *) AllocDosObject(DOS_RDARGS, 0)))
{
rda->RDA_ExtHelp = OPTIONS;
if(ReadArgs(PARAM, (LONG *) &args, rda))
{
if(args.destdir || args.info)
{
struct xadArchiveInfo *ai;
if((ai = (struct xadArchiveInfo *)
xadAllocObjectA(XADOBJ_ARCHIVEINFO, 0)))
{
if(!(err = xadGetInfo(ai, XAD_INFILENAME, args.from,
XAD_NOEXTERN, args.noextern, args.password ? XAD_PASSWORD :
TAG_IGNORE, args.password, TAG_DONE)))
{
if(ai->xai_Flags & XADAIF_FILECORRUPT)
Printf("!!! The archive file has some corrupt data. !!!\n");
if(args.info)
{
struct xadFileInfo *xfi;
ULONG grsize = 0;
Printf("ArchiverName: %s\n"
"Size CrndSize Ratio Date Time Name\n",
ai->xai_Client->xc_ArchiverName);
xfi = ai->xai_FileInfo;
while(xfi && !CTRL_C)
{
if(!(xfi->xfi_Flags & XADFIF_GROUPED))
grsize = 0;
if(xfi->xfi_Flags & XADFIF_DIRECTORY)
{
if(!args.notree)
Printf(" <dir> <dir> %02ld.%02ld.%04ld %02ld:%02ld:%02ld %s\n",
xfi->xfi_Date.xd_Day, xfi->xfi_Date.xd_Month,
xfi->xfi_Date.xd_Year, xfi->xfi_Date.xd_Hour,
xfi->xfi_Date.xd_Minute, xfi->xfi_Date.xd_Second,
xfi->xfi_FileName);
}
else if(xfi->xfi_Flags & XADFIF_GROUPED)
{
Printf("%8ld merged n/a %02ld.%02ld.%04ld %02ld:%02ld:%02ld %s\n",
xfi->xfi_Size, xfi->xfi_Date.xd_Day, xfi->xfi_Date.xd_Month,
xfi->xfi_Date.xd_Year, xfi->xfi_Date.xd_Hour,
xfi->xfi_Date.xd_Minute, xfi->xfi_Date.xd_Second,
args.notree ? FilePart(xfi->xfi_FileName) :
xfi->xfi_FileName);
grsize += xfi->xfi_Size;
if(xfi->xfi_Flags & XADFIF_ENDOFGROUP)
{
ULONG i = 0, j = 0;
if(xfi->xfi_GroupCrSize < grsize)
{
i = ((grsize - xfi->xfi_GroupCrSize)*1000)/grsize;
j = i % 10;
i /= 10;
}
Printf("%8ld %8ld %2ld.%1ld%%\n", grsize, xfi->xfi_GroupCrSize,
i, j);
grsize = 0;
}
}
else
{
ULONG i = 0, j = 0;
if(xfi->xfi_CrunchSize < xfi->xfi_Size)
{
i = ((xfi->xfi_Size - xfi->xfi_CrunchSize)*1000)/xfi->xfi_Size;
j = i % 10;
i /= 10;
}
Printf("%8ld %8ld %2ld.%1ld%% %02ld.%02ld.%04ld %02ld:%02ld:%02ld %s\n",
xfi->xfi_Size, xfi->xfi_CrunchSize, i, j,
xfi->xfi_Date.xd_Day, xfi->xfi_Date.xd_Month,
xfi->xfi_Date.xd_Year, xfi->xfi_Date.xd_Hour,
xfi->xfi_Date.xd_Minute, xfi->xfi_Date.xd_Second,
args.notree ? FilePart(xfi->xfi_FileName) :
xfi->xfi_FileName);
}
if(xfi->xfi_Comment && !args.nocomment)
Printf(": %s\n", xfi->xfi_Comment);
#ifdef DEBUG
if(xfi->xfi_Flags)
{
Printf("Flags: ");
if(xfi->xfi_Flags & XADFIF_CRYPTED)
Printf("XADFIF_CRYPTED ");
if(xfi->xfi_Flags & XADFIF_DIRECTORY)
Printf("XADFIF_DIRECTORY ");
if(xfi->xfi_Flags & XADFIF_LINK)
Printf("XADFIF_LINK ");
if(xfi->xfi_Flags & XADFIF_INFOTEXT)
Printf("XADFIF_INFOTEXT ");
if(xfi->xfi_Flags & XADFIF_GROUPED)
Printf("XADFIF_GROUPED ");
if(xfi->xfi_Flags & XADFIF_ENDOFGROUP)
Printf("XADFIF_ENDOFGROUP ");
if(xfi->xfi_Flags & XADFIF_NODATE)
Printf("XADFIF_NODATE ");
Printf("\n");
}
#endif
if(xfi->xfi_Flags & XADFIF_CRYPTED)
Printf("The entry is encrypted\n");
xfi = xfi->xfi_Next;
}
ret = 0;
}
else
{
struct Hook prhook;
struct xadFileInfo *fi;
UBYTE filename[256];
struct xHookArgs xh;
ret = 0;
xh.name = filename;
xh.flags = xh.finish = 0;
memset(&prhook, 0, sizeof(struct Hook));
prhook.h_Entry = (ULONG (*)()) progrhook;
prhook.h_Data = &xh;
fi = ai->xai_FileInfo;
while(fi && !CTRL_C && !xh.finish)
{
if(!args.file || CheckName(args.file, args.notree ?
FilePart(fi->xfi_FileName) : fi->xfi_FileName))
{
CopyMem(args.destdir, filename, strlen(args.destdir)+1);
if(args.notree)
AddPart(filename, FilePart(fi->xfi_FileName), 256);
else if(!args.noabs)
AddPart(filename, fi->xfi_FileName, 256);
else
{
STRPTR fname = filename, f;
if(*args.destdir)
{
fname += strlen(args.destdir)-1;
if(*fname != ':' && *fname != '/')
*(++fname) = '/';
++fname;
}
for(f = fi->xfi_FileName; *f; ++f)
*(fname++) = *f == ':' ? '/' : *f;
*fname = 0;
}
if(fi->xfi_Flags & XADFIF_DIRECTORY)
{
if(!args.notree)
{
BPTR a;
LONG err = 0, i = 0;
UBYTE r;
while(filename[i] && !err)
{
for(;filename[i] && filename[i] != '/'; ++i)
;
r = filename[i];
filename[i] = 0;
if((a = Lock(filename, SHARED_LOCK)))
UnLock(a);
else if((a = CreateDir(filename)))
UnLock(a);
else
err = 1;
filename[i++] = r;
}
if(err)
Printf("failed to create directory '%s'\n",
fi->xfi_FileName);
else
Printf("Created directory : %s\n", filename);
}
}
else if(fi->xfi_Flags & XADFIF_LINK)
{
Printf("Skipped Link\n");
}
else
{
struct DateStamp d;
if(!xadFileUnArc(ai, XAD_OUTFILENAME, filename,
XAD_ENTRYNUMBER, fi->xfi_EntryNumber, XAD_MAKEDIRECTORY,
!args.askmakedir, XAD_OVERWRITE, args.overwrite,
XAD_PROGRESSHOOK, &prhook, TAG_DONE))
{
if(!args.nodate && !(fi->xfi_Flags & XADFIF_NODATE)
&& !xadConvertDates(XAD_DATEXADDATE, &fi->xfi_Date,
XAD_GETDATEDATESTAMP, &d, TAG_DONE))
SetFileDate(filename, &d);
if(!args.noprot)
SetProtection(filename, fi->xfi_Protection);
if(fi->xfi_Comment && !args.nocomment)
SetComment(filename, fi->xfi_Comment);
/* SetOwner ??? */
}
}
}
fi = fi->xfi_Next;
}
}
xadFreeInfo(ai);
} /* xadGetInfo */
xadFreeObjectA(ai, 0);
} /* xadAllocObject */
}
else
SetIoErr(ERROR_REQUIRED_ARG_MISSING);
FreeArgs(rda);
} /* ReadArgs */
FreeDosObject(DOS_RDARGS, rda);
} /* AllocDosObject */
if(CTRL_C)
SetIoErr(ERROR_BREAK);
if(err)
Printf("An error occured: %s\n", xadGetErrorText(err));
else if(ret)
PrintFault(IoErr(), 0);
CloseLibrary((struct Library *) xadmasterbase);
} /* OpenLibrary xadmaster */
else
Printf("Could not open xadmaster.library\n");
CloseLibrary((struct Library *) dosbase);
} /* OpenLibrary dos */
return ret;
}
/* Because of SAS-err, this cannot be SAVEDS */
ASM(ULONG) progrhook(REG(a0, struct Hook *hook),
REG(a1, struct xadProgressInfo *pi))
{
ULONG ret = 0;
STRPTR name = ((struct xHookArgs *) (hook->h_Data))->name;
switch(pi->xpi_Mode)
{
case XADPMODE_ASK:
ret |= ((struct xHookArgs *) (hook->h_Data))->flags;
if((pi->xpi_Status & XADPIF_OVERWRITE) && !(ret & XADPIF_OVERWRITE))
{
Printf("File '%s' already exists, overwrite? (Y|A|S|\033[1mN\033[0m|Q): ",
name);
Flush(Output());
SetMode(Input(), TRUE);
switch(FGetC(Input()))
{
case 'a': case 'A':
((struct xHookArgs *) (hook->h_Data))->flags |= XADPIF_OVERWRITE;
case 'y': case 'Y': ret |= XADPIF_OVERWRITE; break;
case 's': case 'S': ret |= XADPIF_SKIP; break;
case 'q': case 'Q': ((struct xHookArgs *) (hook->h_Data))->finish = 1;
}
SetMode(Input(), FALSE);
}
if((pi->xpi_Status & XADPIF_MAKEDIRECTORY) &&
!(ret & XADPIF_MAKEDIRECTORY))
{
Printf("Directory of file '%s' does not exist, create? (Y|A|S|\033[1mN\033[0m|Q): ",
name);
Flush(Output());
SetMode(Input(), TRUE);
switch(FGetC(Input()))
{
case 'a': case 'A':
((struct xHookArgs *) (hook->h_Data))->flags |= XADPIF_MAKEDIRECTORY;
case 'y': case 'Y': ret |= XADPIF_MAKEDIRECTORY; break;
case 's': case 'S': ret |= XADPIF_SKIP; break;
case 'q': case 'Q': ((struct xHookArgs *) (hook->h_Data))->finish = 1;
}
SetMode(Input(), FALSE);
}
break;
case XADPMODE_PROGRESS:
Printf("\r\033[KWrote %8ld of %8ld bytes: %s",
pi->xpi_CurrentSize, pi->xpi_FileInfo->xfi_Size, name);
Flush(Output());
break;
case XADPMODE_END: Printf("\r\033[KWrote %8ld bytes: %s\n",
pi->xpi_CurrentSize, name);
break;
case XADPMODE_ERROR: Printf("\r\033[K%s: %s\n", name,
xadGetErrorText(pi->xpi_Error));
break;
}
if(!CTRL_C) /* clear ok flag */
ret |= XADPIF_OK;
return ret;
}
/* would be better to store the pattern parse stuff and do it only once,
but so it is a lot easier */
LONG CheckName(STRPTR *pat, STRPTR name)
{
UBYTE buf[500];
while(*pat)
{
if(ParsePatternNoCase(*(pat++), buf, 500) >= 0)
{
if(MatchPatternNoCase(buf, name))
return 1;
} /* A scan failure means no recognition, should be an error print here */
}
return 0;
}